#include "GYBMP280.h"

GYBMP280_COMPENSATION_COEFFICIENT GYBMP280_Compensation_Coefficient_Inst;
GYBMP280_COMPENSATION_COEFFICIENT* GYBMP280_Compensation_Coefficient = &GYBMP280_Compensation_Coefficient_Inst;

bool GYBMP280_Write1Byte(uint8_t registerAddress, uint8_t byte)
{
	WifiIotI2cData I2cData = {0};

	uint8_t buffer[2] = {registerAddress, byte};    
    I2cData.sendBuf = buffer;
    I2cData.sendLen = 2;

    if(I2cWrite(WIFI_IOT_I2C_IDX_1, (GYBMP280_DEVICE_ADDRESS << 1) | 0x00, &I2cData) == 0)
	{
		return true;
	}
	else
	{
		return false;
	}	
}

uint8_t GYBMP280_Read1Byte(uint8_t registerAddress)
{
	WifiIotI2cData I2cData = {0};

    uint8_t sBuffer[] = {registerAddress};
    I2cData.sendBuf = sBuffer;
    I2cData.sendLen = 1;

    uint8_t rBuffer[] = {0};
    I2cData.receiveBuf = rBuffer;
    I2cData.receiveLen = 1;

    if(I2cWriteread(WIFI_IOT_GPIO_IDX_1, (GYBMP280_DEVICE_ADDRESS << 1) | 0x00, &I2cData) == 0)
    {        
        return rBuffer[0];
    }
    else
    {
        return 0x00;
    }
}

//设置过采样因子模式：GYBMP280_SLEEP_MODE || GYBMP280_FORCED_MODE || GYBMP280_NORMAL_MODE
void GYBMP280_SetOverSampMode(GYBMP280_OVERSAMPLE_MODE *GYBMP280_OverSampleMode)
{
	uint8_t data = ((GYBMP280_OverSampleMode->T_Osample)<<5) | ((GYBMP280_OverSampleMode->P_Osample)<<2) | ((GYBMP280_OverSampleMode)->WORKMODE);
	GYBMP280_Write1Byte(GYBMP280_CTRLMEAS_REG, data);
}

//设置保持时间和滤波器分频因子
void GYBMP280_SetStandbyFilter(GYBMP280_CONFIG *GYBMP280_Config)
{
	uint8_t data = ((GYBMP280_Config->T_SB)<<5) | ((GYBMP280_Config->FILTER_COEFFICIENT)<<2) | ((GYBMP280_Config->SPI_EN));
	GYBMP280_Write1Byte(GYBMP280_CONFIG_REG, data);
}

void GYBMP280_Init(void)
{
	GpioInit();
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA);
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL);
    I2cInit(WIFI_IOT_GPIO_IDX_1, 400000);

	uint8_t byteL,byteH;	
	/********************接下来读出矫正参数*********************/
	//温度传感器的矫正值
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_T1_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_T1_MSB_REG);
	GYBMP280_Compensation_Coefficient->T1 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_T2_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_T2_MSB_REG);
	GYBMP280_Compensation_Coefficient->T2 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_T3_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_T3_MSB_REG);
	GYBMP280_Compensation_Coefficient->T3 = (((uint16_t)byteH)<<8) + byteL;
	
	//大气压传感器的矫正值
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P1_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P1_MSB_REG);
	GYBMP280_Compensation_Coefficient->P1 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P2_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P2_MSB_REG);
	GYBMP280_Compensation_Coefficient->P2 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P3_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P3_MSB_REG);
	GYBMP280_Compensation_Coefficient->P3 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P4_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P4_MSB_REG);
	GYBMP280_Compensation_Coefficient->P4 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P5_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P5_MSB_REG);
	GYBMP280_Compensation_Coefficient->P5 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P6_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P6_MSB_REG);
	GYBMP280_Compensation_Coefficient->P6 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P7_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P7_MSB_REG);
	GYBMP280_Compensation_Coefficient->P7 = (((uint16_t)byteH)<<8) + byteL;	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P8_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P8_MSB_REG);
	GYBMP280_Compensation_Coefficient->P8 = (((uint16_t)byteH)<<8) + byteL;
	
	byteL = GYBMP280_Read1Byte(GYBMP280_DIG_P9_LSB_REG);
	byteH = GYBMP280_Read1Byte(GYBMP280_DIG_P9_MSB_REG);
	GYBMP280_Compensation_Coefficient->P9 = (((uint16_t)byteH)<<8) + byteL;
	
	/******************************************************/
	GYBMP280_Write1Byte(GYBMP280_RESET_REG, GYBMP280_RESET_VALUE);
	
	GYBMP280_OVERSAMPLE_MODE GYBMP280_OverSampleModeStructure;
	GYBMP280_OverSampleModeStructure.P_Osample = GYBMP280_P_MODE_3;
	GYBMP280_OverSampleModeStructure.T_Osample = GYBMP280_T_MODE_1;
	GYBMP280_OverSampleModeStructure.WORKMODE  = GYBMP280_NORMAL_MODE;
	GYBMP280_SetOverSampMode(&GYBMP280_OverSampleModeStructure);
	
	GYBMP280_CONFIG GYBMP280_ConfigStructure;
	GYBMP280_ConfigStructure.T_SB = GYBMP280_T_SB1;
	GYBMP280_ConfigStructure.FILTER_COEFFICIENT = GYBMP280_FILTER_MODE_4;
	GYBMP280_ConfigStructure.SPI_EN = DISABLE;
	
	GYBMP280_SetStandbyFilter(&GYBMP280_ConfigStructure);
}

//获取GYBMP280当前状态
//参数：	GYBMP280_MEASURING || GYBMP280_IM_UPDATE
//返回：	true成功，false失败
bool GYBMP280_GetStatus(uint8_t statusFlag)
{
	uint8_t flag = GYBMP280_Read1Byte(GYBMP280_STATUS_REG);
	if(flag & statusFlag)
	{
		return true;
	}
	else
	{
		return false;
	}
}

S32_t t_fine;//用于计算补偿
//我用浮点补偿
#ifdef USE_FIXED_POINT_COMPENSATE
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. 
// t_fine carries fine temperature as global value
S32_t GYBMP280_CompensateAtmosphericTemperatureToInt32(S32_t adc_T)
{
	S32_t var1, var2, T;
	var1 = ((((adc_T>>3) - ((S32_t)dig_T1<<1))) * ((S32_t)dig_T2)) >> 11;
	var2 = (((((adc_T>>4) - ((S32_t)dig_T1)) * ((adc_T>>4) - ((S32_t)dig_T1))) >> 12) * ((S32_t)dig_T3)) >> 14;
	t_fine = var1 + var2;
	T = (t_fine * 5 + 128) >> 8;
	return T;
}

// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
U32_t GYBMP280_CompensateAtmosphericPressureToInt64(S32_t adc_P)
{
	S64_t var1, var2, P;
	var1 = ((S64_t)t_fine) - 128000;
	var2 = var1 * var1 * (S64_t)dig_P6;
	var2 = var2 + ((var1*(S64_t)dig_P5)<<17);
	var2 = var2 + (((S64_t)dig_P4)<<35);
	var1 = ((var1 * var1 * (S64_t)dig_P3)>>8) + ((var1 * (S64_t)dig_P2)<<12);
	var1 = (((((S64_t)1)<<47)+var1))*((S64_t)dig_P1)>>33;
	if (var1 == 0)
	{
		return 0; // avoid excePtion caused by division by zero
	}
	else
	{
		P = 1048576-adc_P;
		P = (((P<<31)-var2)*3125)/var1;
		var1 = (((S64_t)dig_P9) * (P>>13) * (P>>13)) >> 25;
		var2 = (((S64_t)dig_P8) * P) >> 19;
		P = ((P + var1 + var2) >> 8) + (((S64_t)dig_P7)<<4);
		return (U32_t)P;
	}
}
/***********************************CUT*************************************/
#else
/**************************传感器值转定点值*************************************/
// Returns temperature in DegC, double precision. Output value of “51.23” equals 51.23 DegC.
// t_fine carries fine temperature as global value
double GYBMP280_CompensateAtmosphericTemperatureToDouble(S32_t adc_T)
{
	double var1, var2, T;
	var1 = (((double)adc_T)/16384.0 - ((double)dig_T1)/1024.0) * ((double)dig_T2);
	var2 = ((((double)adc_T)/131072.0 - ((double)dig_T1)/8192.0) * (((double)adc_T)/131072.0 - ((double) dig_T1)/8192.0)) * ((double)dig_T3);
	t_fine = (S32_t)(var1 + var2);
	T = (var1 + var2) / 5120.0;
	return T;
}

// Returns pressure in Pa as double. Output value of “96386.2” equals 96386.2 Pa = 963.862 hPa
double GYBMP280_CompensateAtmosphericPressureToDouble(S32_t adc_P)
{
	double var1, var2, P;
	var1 = ((double)t_fine/2.0) - 64000.0;
	var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
	var2 = var2 + var1 * ((double)dig_P5) * 2.0;
	var2 = (var2/4.0)+(((double)dig_P4) * 65536.0);
	var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0;
	var1 = (1.0 + var1 / 32768.0)*((double)dig_P1);
	if (var1 == 0.0)
	{
		return 0; // avoid excePtion caused by division by zero
	}
	else
	{
		P = 1048576.0 - (double)adc_P;
		P = (P - (var2 / 4096.0)) * 6250.0 / var1;
		var1 = ((double)dig_P9) * P * P / 2147483648.0;
		var2 = P * ((double)dig_P8) / 32768.0;
		P = P + (var1 + var2 + ((double)dig_P7)) / 16.0;
		return P;
	}
}
#endif

//获取大气温度值单位：℃
double GYBMP280_GetAtmosphericTemperature(void)
{
	uint8_t byteD = GYBMP280_Read1Byte(GYBMP280_TEMPERATURE_XLSB_REG);
	uint8_t byteL = GYBMP280_Read1Byte(GYBMP280_TEMPERATURE_LSB_REG);
	uint8_t byteH = GYBMP280_Read1Byte(GYBMP280_TEMPERATURE_MSB_REG);
	long signed T = ((long)(byteH<<12)) | ((long)(byteL<<4)) | (byteD>>4);
	double temperature = GYBMP280_CompensateAtmosphericTemperatureToDouble(T);
	return temperature;
}

//获取大气压强值单位：Pa
double GYBMP280_GetAtmosphericPressure(void)
{
	uint8_t byteD = GYBMP280_Read1Byte(GYBMP280_PRESSURE_XLSB_REG);
	uint8_t byteL = GYBMP280_Read1Byte(GYBMP280_PRESSURE_LSB_REG);
	uint8_t byteH = GYBMP280_Read1Byte(GYBMP280_PRESSURE_MSB_REG);
	long signed P = ((long)(byteH<<12)) | ((long)(byteL<<4)) | (byteD>>4);
	double pressure = GYBMP280_CompensateAtmosphericPressureToDouble(P);
	return pressure;
}

//获取海拔高度单位：ｍ
double GYBMP280_GetAltitude(void)
{
	double pressure = GYBMP280_GetAtmosphericPressure();
	double temperature = GYBMP280_GetAtmosphericTemperature();
	double altitude = 18400 * (1 + temperature/273.15) * log(101325.0/pressure);//拉普拉斯压高公式
	return altitude;
}
